﻿using BarcodeDelay;
using JTParcrelHelper.business;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading.Tasks;

namespace JTParcrelHelper.MessageClient
{
    public class MessageQQProClient
    {
        public const int MAX_FRAME_LENGTH = 1024 * 10;
        public const int FRAME_LENGTH = 4;
        public event EventHandler<EargsClientConnect> OnStationConnectEvent;
        public event EventHandler<EargsClientDisconnect> OnStationDisconnectEvent;
        public event EventHandler<EargsMessageReceives> OnMessageEvent;

        public const string MESSAGE_KEY = "ScaleWeight";

        private string serverIp;
        private int serverPort;
        private string serverKey = "Scale";
        private const string CLIENT_REMOTE_IP_KEY = "ClientRemoteIp";
        private const string CLIENT_REMOTE_PORT_KEY = "ClientRemotePort";
        private bool isNetArrived = false;
        private Socket clientSocket = null;
        private object socketLock = new object();
        private Boolean manualClosed = false;

        private DateTime dtLastHeartBeat = System.DateTime.Now.AddSeconds(2);
        private bool isInProcessTimer = false;

        

        #region 单例方法
        private static MessageQQProClient instance;
        public static MessageQQProClient Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new MessageQQProClient();
                }
                return instance;
            }
        }
        private MessageQQProClient()
        {
        }
        #endregion

        #region 属性
        public string ServerIp
        {
            get { return serverIp; }
            set { serverIp = value; }
        }

        public int ServerPort
        {
            get { return serverPort; }
            set { serverPort = value; }
        }

        public bool IsNetArrived
        {
            get { return isNetArrived; }
            set { this.isNetArrived = value; }
        }

        public Socket ClientSocket
        {
            get { return this.clientSocket; }
        }
        #endregion

        #region 公共接口
        public void Init()
        {
            try
            {
                ServerTimeTickManager.Instance.OnServerTimeTickEvent += this.ServerTimeTickHandler;

                if (ServiceManager.Instance.CurrentExecutor.Execute(new MessageQQReceiveTask(this)) == 0)
                {
                    //Logger.LogDebug("JsonAccessProClient.Init()", "【MessageClient】： Start receive task successfully.");
                }

            }
            catch (System.Exception ex)
            {
                BarcodeDelay.logHelp.LogHelper.Instance.writeLog("定时器发生异常"+ex.ToString());

                //Logger.LogError("JsonAccessProClient.Init()", "【MessageClient】： Init Error--ex ： " + ex.Message);
            }
        }

        public void ReadConfiguration()
        {
            string methodStr = "JsonAccessClient.ReadConfguration";
            try
            {
                //this.serverIp = "192.168.3.120";
                //this.serverIp = "127.0.0.1";
                //this.serverPort = 9990;

                this.serverIp = ConfigurationManager.AppSettings["QQMsgTransferServer"];
                this.serverPort = Convert.ToInt32(ConfigurationManager.AppSettings["QQMsgTransferPort"]);

        

            }
            catch (System.Exception ex)
            {
                //SimbaCameraScale.Common.Log.//Logger.LogError(methodStr, "【MessageClient】： Read Configuration Failed : Exception : " + ex.Message);
            }
        }

        public void ShutDown()
        {
            if (ServiceManager.Instance.IsTaskRunning(MessageQQReceiveTask.TASK_NAME))
            {
                IServiceTask task = ServiceManager.Instance.CurrentExecutor.GetTaskByName(MessageQQReceiveTask.TASK_NAME);
                if (task != null)
                {
                    task.CancelTask();
                }
            }
        }

        public Boolean IsSocketConnect()
        {
            return ((this.clientSocket != null) && (this.clientSocket.Connected));
        }

        public void TriggerStationDisconnectEvent(object sender, EargsClientDisconnect args)
        {
            if (this.OnStationDisconnectEvent != null)
            {
                EventHandlerTrigger.TriggerEvent<EargsClientDisconnect>(this.OnStationDisconnectEvent,
                                                 sender, args);
            }
        }

        public void ReceiveEntireMessage(byte[] realContent)
        {
            string jsonContent = System.Text.Encoding.UTF8.GetString(realContent);
            BarcodeDelay.logHelp.LogHelper.Instance.writeLog(jsonContent);
            if (jsonContent.Contains("heartBeatServer"))
            {
                dtLastHeartBeat = System.DateTime.Now;
                
                return;
            }
            


            EargsMessageReceives msg = new EargsMessageReceives(MESSAGE_KEY, jsonContent);
            this.TriggerMessageReceivedEvent(this, msg);
        }

        public void ManualCloseSocket()
        {
            try
            {
                if (IsSocketConnect())
                {
                    manualClosed = true;

                    clientSocket.Close();

                    //Logger.LogInfo("CloseWebAccessClientSocket", "【MessageClient】： Socket manually closed successfully.");
                }
            }
            catch (Exception ex)
            {
                //Logger.LogError("CloseWebAccessClientSocket", "【MessageClient】： Socket manually closed error : " + ex.Message);
            }
            finally
            {
                clientSocket = null;
            }
        }

        public void ManualOpenSocket()
        {
            manualClosed = false;

            //Logger.LogInfo("CloseWebAccessClientSocket", "【MessageClient】： Socket manually open successfully.");
        }

        public int SendContent(byte[] sendBuffer)
        {
            ////Logger.LogError(null, "SCK发送请求:");
            if (sendBuffer == null || sendBuffer.Length <= 0)
            {
                return 1;
            }

            if (!this.IsSocketConnect())
            {
                //PacketInfo.Instance.WriteLog("Debug", "Socket连接断开,SendRequest无法发送请求指令");
                //Logger.LogError(null, "Socket连接断开,SendRequest无法发送请求指令");
                return 2;
            }

            try
            {
                this.clientSocket.Send(sendBuffer);
                //PacketInfo.Instance.WriteLog("Debug", "SendRequest发送了请求");

                //Logger.LogInfo(null, "SendRequest发送了请求");

                return 0;
            }
            catch (Exception ex)
            {
                //Logger.LogError(null, "SCK发送请求时捕获异常:" + ex.Message);
                return 3;
            }
        }
        #endregion

        #region 私有方法
        private void ServerTimeTickHandler(object sender, EargsTimeTick e)
        {
            if(isInProcessTimer)
            {
                return;
            }

            if (StoParams.Instance.isZCOperater)
            {
                return;
            }

            isInProcessTimer = true;
            if (manualClosed)
            {
                isInProcessTimer = false; 
                return;
            }
            TimeSpan ts = System.DateTime.Now - dtLastHeartBeat;
            if(ts.TotalSeconds>6)
            {
                BarcodeDelay.logHelp.LogHelper.Instance.writeLog("QQ transfer心跳超时，断开重连");
                if(this.clientSocket!=null)
                {
                    try
                    {
                        this.clientSocket.Close();
                        this.clientSocket = null;
                        BarcodeDelay.logHelp.LogHelper.Instance.writeLog("QQ transfer 断开完成");
                    }
                    catch(Exception ex2)
                    {
                        BarcodeDelay.logHelp.LogHelper.Instance.writeLog("QQ transfer 断开发生异常：" + ex2.ToString());
                    }
                    
                }
                
                dtLastHeartBeat = System.DateTime.Now;
                isInProcessTimer = false;
            }

            if (CheckStatus.IsIPConn(this.serverIp, 1000))
            {
                this.IsNetArrived = true;
            }
            else
            {
                isInProcessTimer = false;
                this.isNetArrived = false;
                return;
            }

            if (!IsSocketConnect())
            {
                //Logger.LogWarn("ServerTimeTickHandler", "【MessageClient】：Server lost connection, try to reconnect.");
                this.ConnectToServer();
            }
            isInProcessTimer = false;
        }

        private void ConnectToServer()
        {
            lock (socketLock)
            {
                //Double Check
                if (IsSocketConnect())
                {
                    return;
                }

                this.DoConnect();
            }
        }

        private void DoConnect()
        {
            
            string methodStr = "DoConnect";
            try
            {
                Socket tSck = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPEndPoint acsEndPoint = new IPEndPoint(IPAddress.Parse(this.serverIp.Trim()), this.serverPort);

                tSck.Connect(acsEndPoint);

                if (tSck.Connected)
                {
                    BarcodeDelay.logHelp.LogHelper.Instance.writeLog("连接QQtransfer服务端成功");
                    this.clientSocket = tSck;
                    //Logger.LogInfo(methodStr, "【MessageClient】： Socket connected to server --【" + this.serverIp + "】");
                    this.TriggerStationConnectEvent(this, new EargsClientConnect());
                }
                else
                {
                    BarcodeDelay.logHelp.LogHelper.Instance.writeLog("连接QQtransfer 服务器失败");
                    //Logger.LogWarn(methodStr, "【MessageClient】： Socket connected failed.");
                }
            }
            catch (Exception ex)
            {
                BarcodeDelay.logHelp.LogHelper.Instance.writeLog("连接QQ transfer 异常:" + ex.ToString());
                //Logger.LogError(null, "【MessageClient】： Socket connecting exception : " + ex.Message);
            }
        }

        private void TriggerMessageReceivedEvent(object sender, EargsMessageReceives args)
        {
            if (this.OnMessageEvent != null)
            {

                EventHandlerTrigger.TriggerEvent<EargsMessageReceives>(this.OnMessageEvent,
                                                 sender, args);
            }
        }

        private void TriggerStationConnectEvent(object sender, EargsClientConnect args)
        {
            if (this.OnStationConnectEvent != null)
            {
                EventHandlerTrigger.TriggerEvent<EargsClientConnect>(this.OnStationConnectEvent,
                                                 sender, args);
            }
        }
        #endregion

        //////////////////////////////////////////////////////////////////////////End Of Class
    }
}
